﻿using iTool.Cloud.Center.Model;
using iTool.Clustering.Center.ServiceProvider;
using iTool.Common;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Orleans;
using Orleans.Configuration;
using Orleans.Hosting;
using System.Net;
using System.Threading.Tasks;
using iTool.Cloud.Center.Logger;
using iTool.Cloud.Center.ServiceProvider;

namespace iTool.Clustering.Center
{
    

    public static class iCenter
    {
        internal static IGrainFactory? iGrainFactory;

        public static async Task<IApplicationBuilder> RegisteriToolCenterAsync(this IApplicationBuilder app,ServiceEndPointOptions configureOptions, ClusterIdentificationOptions? clusterOptions = null)
        {
            await RegisteriToolCenterAsync(configureOptions, clusterOptions);
            return app;
        }

        public static async Task<iCenterHost> RegisteriToolCenterAsync(ServiceEndPointOptions configureOptions, ClusterIdentificationOptions? clusterOptions = null)
        {
            iPrint.Line("\niTool> Start Builder iToolCenter...");

            clusterOptions = clusterOptions ?? new ClusterIdentificationOptions();

            SiloHostBuilder builder = new SiloHostBuilder();

            builder.Configure<ClusterOptions>(options =>
            {
                options.ClusterId = clusterOptions.ClusterId;
                options.ServiceId = clusterOptions.ServiceId;
            });

            builder.ConfigureEndpoints(IPAddress.Parse(configureOptions.Host), configureOptions.Port, configureOptions.GatewayPort, true);

            builder.UseLocalhostClustering(
                    configureOptions.Port,
                    configureOptions.GatewayPort,
                    serviceId: clusterOptions.ServiceId,
                    clusterId: clusterOptions.ClusterId);

            builder.ConfigureApplicationParts(parts => parts.AddApplicationPart(typeof(ClusterClientService).Assembly).WithCodeGeneration().WithReferences());

            builder.ConfigureLogging(configureLogging => configureLogging.AddCenterLogger(configureLogging =>
            {
                configureLogging.MinLogLevel = Microsoft.Extensions.Logging.LogLevel.Warning;
                configureLogging.ProviderName = "iToolCenterGateway";
            }));

            ISiloHost hoster = builder.Build();

            await hoster.StartAsync();

            iGrainFactory = hoster.Services.GetService<IGrainFactory>();

            iPrint.Success("\niTool> Started successfully.");

            return new CenterHost(hoster);

        }
    }


    public interface iCenterHost
    {
        ValueTask StopAsync();
        T GetService<T>();
        IClusterLoggerService GetLoggerService(string providerName = "DefaultLogger");
    }

    public class CenterHost : iCenterHost
    {
        ISiloHost hoster;
        public CenterHost(ISiloHost hoster)
        {
            this.hoster = hoster;
        }

        public IClusterLoggerService GetLoggerService(string providerName = "DefaultLogger")
        {
            return iCenter.iGrainFactory?.GetGrain<IClusterLoggerService>(providerName);
        }

        public T GetService<T>()
        {
            return hoster.Services.GetService<T>();
        }

        public async ValueTask StopAsync()
        {
            await hoster.StopAsync();
        }
    }
}
